package net.opentsdb.core;


import net.opentsdb.query.filter.TagVFilter;
import org.hbase.async.Bytes;

import java.util.*;

public final class Tags {

    public static String[] splitString(String s, char c) {
        final char[] chars = s.toCharArray();
        int num_substrings = 1;
        for (final char x : chars) {
            if (x == c) {
                num_substrings++;
            }
        }
        final String[] result = new String[num_substrings];
        final int len = chars.length;
        int start = 0;  // starting index in chars of the current substring.
        int pos = 0;    // current index in chars.
        int i = 0;      // number of the current substring.
        for (; pos < len; pos++) {
            if (chars[pos] == c) {
                result[i++] = new String(chars, start, pos - start);
                start = pos + 1;
            }
        }
        result[i] = new String(chars, start, pos - start);
        return result;
    }

    public static long parseLong(String replace) {
        return 1L;
    }

    public static void parse(Map tags, String cmd) {
        final String[] kv = splitString(cmd, '=');
        if (kv.length != 2 || kv[0].length() <= 0 || kv[1].length() <= 0) {
            throw new IllegalArgumentException("invalid tag: " + cmd);
        }
        if (kv[1].equals(tags.get(kv[0]))) {
            return;
        }
        if (tags.get(kv[0]) != null) {
            throw new IllegalArgumentException("duplicate tag: " + cmd
                    + ", tags=" + tags);
        }
        tags.put(kv[0], kv[1]);
    }

    public static boolean looksLikeInteger(String value) {
        final int n = value.length();
        for (int i = 0; i < n; i++) {
            final char c = value.charAt(i);
            if (c == '.' || c == 'e' || c == 'E'){
                return false;
            }
        }
        return true;
    }

    public static boolean fitsInFloat(String value) {
        final double d = Double.parseDouble(value);
        return ((float) d) == d;
    }

    public static ArrayList<byte[]> resolveOrCreateAll(TSDB tsdb, Map<String, String> tags) {
        return resolveAllInternal(tsdb,tags,true);
    }

    private static ArrayList<byte[]> resolveAllInternal(TSDB tsdb, Map<String, String> tags, boolean b) {
        ArrayList tag_ids = new ArrayList<byte[]>(tags.size());
        for(Map.Entry<String,String> entry :tags.entrySet()){
            byte[] tag_id = tsdb.tag_names.getOrCreateId(entry.getKey());
            byte[] value_id = tsdb.tag_values.getOrCreateId(entry.getValue());
            byte[] thistag = new byte[tag_id.length+value_id.length];
            System.arraycopy(tag_id,0,thistag,0,tag_id.length);
            System.arraycopy(value_id,0,thistag,tag_id.length,value_id.length);
            tag_ids.add(thistag);
        }
        Collections.sort(tag_ids, Bytes.MEMCMP);
        return tag_ids;
    }

    public static String parseWithMetricAndFilters(String metric, List<TagVFilter> filters) {
        if(metric ==null){

        }
        final  int curly  = metric.indexOf('{');
        if(curly<0){
            return metric;
        }
        final int len = metric.length();
        if(metric.charAt(len-1)!='}'){

        }else if (curly==len-2){
            return metric.substring(0,len-2);
        }
        final int close = metric.indexOf('}');
        HashMap <String ,String> filter_map = new HashMap<>();
        if(close!=metric.length()-1){
            int filter_bracket = metric.lastIndexOf('{');
            for(String filter:splitString(metric.substring(filter_bracket+1,metric.length()-1),',')){
                if(filter.isEmpty()){
                    break;
                }

                filter_map.clear();

                parse(filter_map,filter);
                TagVFilter.mapToFilters(filter_map,filters,false);

            }
        }

        for(String tag:splitString(metric.substring(curly+1,close),',')){
            if(tag.isEmpty()){
                break;
            }
            filter_map.clear();
            parse(filter_map,tag);
            TagVFilter.tagsToFilters(filter_map,filters);
        }

        return metric.substring(0,curly);

    }
}
